<?php
declare (strict_types=1);

namespace app\controller;

use app\BaseController;
use app\common\Amap;
use app\common\UsersService;
use app\model\Config;
use app\model\HkArea;
use app\model\Notice;
use app\model\Store;
use app\model\StoreAssess;
use app\model\StoreAssessComment;
use app\model\StoreClass;
use app\model\UsersRelated;
use app\model\UsersShield;
use app\Request;
use app\tool\GpsUtils;
use app\tool\Http;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\response\Json;

class StoreController extends BaseController
{
    protected array $middleware = [
        'Login' => ['except' => ['test','class', 'get_data', 'index', 'class_third', 'list', 'notice', 'read', 'comment_list','assess_detail','same','search']],
        'Location' => ['only' => ['index', 'list', 'read', 'assess_detail']],
    ];
	
	/**
	 * 屏蔽
	 * @param Request $request
	 * @return void
	 */
	function shield(Request $request)
	{
		$id = $request->post('id/d');
		UsersShield::create([
			'users_id'=>$request->users_id,
			'pro_id'=>$id,
			'type'=>'store'
		]);
		writeJson();
	}
	
	
	/**
	 * 评价列表
	 * @param mixed $hk_area_id
	 * @param int $default
	 * @param string $keyword
	 * @return Json
	 */
    public function index(Request $request,mixed $hk_area_id, int $default, string $keyword)
    {
	    
	    $shield = UsersShield::where(['users_id'=>$request->users_id,'type'=>'store'])->column('pro_id');
	    
	    $lat = self::$latitude;
        $lng = self::$longitude;

        $rows = StoreAssess::with(['users'])
	        ->withJoin([
		        'store'	=>	function (Query $query)use($lat,$lng){
					$query->field("(6371 * acos (cos ( radians($lat) ) * cos( radians( latitude ) ) * cos( radians(longitude) - radians( $lng ) ) + sin ( radians( $lat ) ) * sin( radians( latitude ) ))) as distance");
			}])
	        ->when(!empty($hk_area_id)&&$hk_area_id!=3, function (Query $query) use ($hk_area_id) {
		        $query->whereFindInSet('store.hk_area_ids',$hk_area_id);
	        })
	        ->whereNotIn('store_assess.id',$shield)
            ->when(!empty($default), function (Query $query) use ($default,$lng,$lat) {
                switch ($default) {
                    case 1:
                        $query->order('id', 'desc');
                        break;
                    case 2:
                        $query->order('browse', 'desc');
                        break;
                    case 3:
                        $query->order('createtime', 'desc');
                        break;
                    case 4:
                        $query->where('images', '<>', '');
                        break;
                    case 5:
                        if (empty($lat) || empty($lng)) {
                            $query->order('createtime', 'desc');
                        } else {
                            $query->order('distance', 'asc');
                        }
                        break;
                }
            })
            ->when(!empty($keyword), function (Query $query) use ($keyword) {
                $query->whereLike('store_assess.title|store_assess.content', '%' . $keyword . '%');
            })
            ->paginate()
            ->items();
        writeJson($rows);

    }
	
	/**
	 * 搜索
	 * @param string $keyword
	 * @return void
	 * @throws DbException
	 */
    function search(string $keyword)
    {
        if (empty($keyword)) {
            writeJson(0,'无效关键词');
        }
		
	    $list['Store']['count'] = Store::whereLike('title|content', '%' . $keyword . '%')->count();
	    $list['StoreAssess']['count'] = StoreAssess::whereLike('title|content', '%' . $keyword . '%')->count();
		
        writeJson($list);
    }
	
	/**
	 * 商铺列表
	 * @param int $class_id 三级分类ID
	 * @param int $default
	 * @param string $keyword
	 * @param mixed $hk_area_id
	 * @return Json
	 */
    function list(mixed $class_id, int $default, string $keyword,mixed $hk_area_id)
    {
        $lat = self::$latitude;
        $lng = self::$longitude;
        $rows = Store::field("*,(6371 * acos (cos ( radians($lat) ) * cos( radians( latitude ) ) * cos( radians(longitude) - radians( $lng ) ) + sin ( radians( $lat ) ) * sin( radians( latitude ) ))) AS distance")
            ->when(!empty($class_id), function (Query $query) use ($class_id) {
                    $query->where(['class_id' => $class_id]);
            })
	        ->when(!empty($hk_area_id)&&$hk_area_id!=3, function (Query $query) use ($hk_area_id) {
		        $query->whereFindInSet('hk_area_ids',$hk_area_id);
	        })
            ->filter(function ($data) {
                if (empty($data->logo_image)) {
                    $store_assess = StoreAssess::where(['store_id' => $data->id, ['images', '<>', '']])->order(['like' => 'desc'])->find();
                    if ($store_assess) {
                        $logo_images = $store_assess->images;
                    } else {
                        $logo_images = Config::where(['name' => 'store'])->value('value');
                    }
                    if (!empty($logo_images)) {
                        $data->logo_image = config('app.static_host') . explode(',', $logo_images)[0];
                    }
                }
                if (empty($lat) || empty($lng)) {
                    $data->distance_text = '';
                } else {
                    if ($data->distance == 0) {
                        $data->distance_text = '0m';
                    } elseif (0 < $data->distance && $data->distance < 1) {
                        $data->distance_text = bcmul((string)$data->distance, '1000') . 'm';
                    } else {
                        $data->distance_text = bcmul((string)$data->distance, '1', 1) . 'km';
                    }
                }
            })
            ->when(!empty($default), function (Query $query) use ($default,$lng,$lat) {
                switch ($default) {
                    case 1:
                        $query->order('id', 'desc');
                        break;
                    case 2:
                        $query->order('browse', 'desc');
                        break;
                    case 3:
                        $query->order('createtime', 'desc');
                        break;
                    case 4:
                        $query->where('image', '<>', '');
                        break;
                    case 5:
                        if (empty($lat) || empty($lng)) {
                            $query->order('createtime', 'desc');
                        } else {
                            $query->order('distance', 'asc');
                        }
                        break;
                }
            })
            ->when(!empty($keyword), function (Query $query) use ($keyword) {
                $query->whereLike('title', '%' . $keyword . '%');
            })
            ->paginate()
            ->items();

        writeJson($rows);

    }


    /**
     * 本地商圈-发布
     * @param Request $request
     * @return \think\response\Json
     */
    public function save(Request $request)
    {
	    $params = $request->param();
	    if (!empty($params['longitude'])&&!empty($params['latitude'])){
		    $ids = HkArea::where([['top','>=',$params['latitude']],['bottom','<=',$params['latitude']],['left','<=',$params['longitude']],['right','>=',$params['longitude']]])->column('id');
		    $ids = implode(',',$ids);
		    $params['hk_area_ids'] = $ids;
	    }
	    
	    $res = Store::create($params);
        Notice::create(['users_id' => $request->users_id, 'type' => 3, 'content' => '恭喜' . $params['title'] . '商家入驻成功', 'pro_id' => $res->id]);
        writeJson();
    }

    /**
     * 动态广播
     * @return Json
     */
    function notice()
    {
        $rows = Notice::where(['type' => 3])->limit($this->page_rows)->order(['id' => 'desc'])->select();
        writeJson($rows);
    }

    /**
     * 详情
     * @param int $id
     * @return Json
     */
    public function read(int $id)
    {
        $lat = self::$latitude;
        $lng = self::$longitude;
        $row = Store::field("*,(6371 * acos (cos ( radians($lat) ) * cos( radians( latitude ) ) * cos( radians(longitude) - radians( $lng ) ) + sin ( radians( $lat ) ) * sin( radians( latitude ) ))) AS distance")
            ->with(['class'])
            ->filter(function ($data) use ($lat, $lng) {
                if (empty($lat) || empty($lng)) {
                    $data->distance_text = '';
                } else {
	                if (empty($data->latitude)||empty($data->longitude)){
		                $data->distance_text = '';
	                }else{
		                if ($data->distance == 0) {
			                $data->distance_text = '0m';
		                } elseif (0 < $data->distance && $data->distance < 1) {
			                $data->distance_text = bcmul(number_format($data->distance,6), '1000') . 'm';
		                } else {
			                $data->distance_text = bcmul((string)$data->distance, '1', 1) . 'km';
		                }
	                }
                }

            })
            ->find($id);
	    event('StoreIncBrowse', $id); //增加浏览数量
	    
	    writeJson($row);
    }
	
	
	/**
	 * 评价详情
	 * @param int $id
	 * @param Request $request
	 * @return Json
	 */
    function assess_detail(int $id, Request $request)
    {
        $lat = self::$latitude;
        $lng = self::$longitude;
        $row = StoreAssess::with([
            'store' => function (Query $query) use ($lat, $lng) {
                $query->field("*,(6371 * acos (cos ( radians($lat) ) * cos( radians( latitude ) ) * cos( radians(longitude) - radians( $lng ) ) + sin ( radians( $lat ) ) * sin( radians( latitude ) ))) AS distance")
                    ->filter(function ($data) use($lat,$lng) {
                        if (empty($lat) || empty($lng)) {
                            $data->distance_text = '';
                        } else {
                            if ($data->distance == 0) {
                                $data->distance_text = '0m';
                            } elseif (0 < $data->distance && $data->distance < 1) {
                                $data->distance_text = bcmul((string)$data->distance, '1000') . 'm';
                            } else {
                                $data->distance_text = bcmul((string)$data->distance, '1', 1) . 'km';
                            }
                        }
                    })
                    ->with(['class']);
            },
            'users',
            'users_like' => function (Query $query) use ($request) {
                $query->where(['users_id' => $request->users_id, 'type' => 'store_assess']);
            },
            'users_collect' => function (Query $query) use ($request) {
                $query->where(['users_id' => $request->users_id, 'type' => 'store_assess']);
            },
        ])->find($id);
        $row->browse += 1;
        $row->save();
        writeJson($row);
    }


    function class()
    {
        $rows = StoreClass::with(['class' => function (Query $query) {
            $query->with(['class']);
        }])
	        ->where(['pid' => 0])
	        ->select();
        writeJson($rows);
    }

    /**
     * 三级ID
     * @param int $class_id
     * @return Json
     */
    function class_third(int $class_id)
    {
        $rows = StoreClass::where(['pid' => $class_id])->select();
        writeJson($rows);
    }


    /**
     * 相似评价
     * @param int $id
     * @return Json
     */
    function same(int $id)
    {
        $rows = StoreAssess::where(['store_id' => $id])
            ->with(['users'])
            ->order(['id' => 'desc'])
            ->paginate()
	        ->items();
        writeJson($rows);

    }

    /**
     * 评价
     * @param Request $request
     * @return Json
     */
    function assess(Request $request)
    {
        $params = $request->param();
		$store = Store::findOrFail($params['store_id']);
	    $params['class_id']=$store->class_id;
        StoreAssess::create($params);
        writeJson();
    }

    /**
     * 评价-评论
     * @param Request $request
     * @return Json
     */
    function comment(Request $request): Json
    {
        $params = $request->param();
        $ip = $request->ip();
        $params['ip'] = $ip;
        $ip = Amap::ip($ip);
        $ip = json_decode($ip);
        if ($ip->status == 1) {
            $params['city'] = $ip->province;
        } else {
            $params['city'] = '未知';
        }
        $res = StoreAssessComment::create($params);
        foreach ($params['content'] as $v) {
            if ($v['type'] == 'at') {
                //@提醒  提醒接收人
                UsersRelated::create(['users_id' => $v['userId'], 'type' => 8, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $res->id]);
            }
        }
        if (!empty($params['to_users_id'])) {
            //回复提醒  提醒接收人
            UsersRelated::create(['users_id' => $params['to_users_id'], 'type' => 1, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $res->id]);
        } else {
            //评论提醒  提醒发布人
            $pro = StoreAssess::find($params['assess_id']);
            UsersRelated::create(['users_id' => $pro->users_id, 'type' => 2, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $res->id]);
        }
        event('StoreAssessIncComment', $params['assess_id']); //增加评论数量

        $row = StoreAssessComment::with(['users', 'to_users', 'users_like' => function (Query $query) use ($request) {
            $query->where(['users_id' => $request->users_id, 'type' => 'store_assess_comment']);
        }])->find($res->id);
        writeJson($row);
    }

    /**
     * 评论列表
     * @param int $assess_id
     * @param mixed $comment_id
     * @param Request $request
     * @return Json
     */
    function comment_list(int $assess_id, mixed $comment_id, Request $request)
    {
        $top_id = 0;
        if (!empty($comment_id)) {
            $row = StoreAssessComment::find($comment_id);
            if ($row->pid == 0) {
                //顶级评论 放在第一条
                $top_id = $row->id;
            } else {
                //子评论 找出顶级评论
                $row = StoreAssessComment::find($row->pid);
                $top_id = $row->id;
            }
        }

        $rows = StoreAssessComment::where(['pid' => 0, 'assess_id' => $assess_id])
            ->withCount('comment')
            ->with([
                'users',
                'users_like' => function (Query $query) use ($request) {
                    $query->where(['users_id' => $request->users_id, 'type' => 'store_assess_comment']);
                },
                'comment' => function (Query $query) use ($request, $comment_id) {
                    $query
                        ->with(['users', 'to_users', 'users_like' => function (Query $query) use ($request) {
                            $query->where(['users_id' => $request->users_id, 'type' => 'store_assess_comment']);
                        }])
                        ->when(!empty($comment_id), function (Query $query) use ($comment_id) {
                            $query->field("*,IF(id = $comment_id,1,0) AS top")->order(['top' => 'desc', 'id' => 'desc']);
                        }, function (Query $query) {
                            $query->order(['id' => 'desc']);
                        })
                        ->limit($this->comment_list_rows);
                }])
            ->when(!empty($comment_id), function (Query $query) use ($top_id) {
                $query->field("IF(id = $top_id,1,0) AS top")->order(['top' => 'desc', 'id' => 'desc']);
            }, function (Query $query) {
                $query->order(['id' => 'desc']);
            })
            ->paginate()
            ->items();
        writeJson($rows);
    }

    /**
     * 评论详情
     * @param int $id
     * @param mixed $comment_id
     * @param Request $request
     * @return Json
     */
    function comment_detail(int $id, mixed $comment_id, Request $request)
    {
        $child = false;
        if (!empty($comment_id)) {
            $row = StoreAssessComment::find($comment_id);
            if ($row->pid != 0) {
                //二级评论
                $child = true;
            }
        }
        $rows = StoreAssessComment::where(['pid' => $id])
            ->with(['users', 'to_users', 'users_like' => function (Query $query) use ($request) {
                $query->where(['users_id' => $request->users_id, 'type' => 'store_assess_comment']);
            }])
            ->when($child, function (Query $query) use ($comment_id) {
                $query->where('id', '<>', $comment_id);
            })
            ->order(['id' => 'desc'])
            ->paginate($this->comment_detail_rows)
            ->items();
        writeJson($rows);
    }
	
	/**
	 * 评论点赞
	 * @param Request $request
	 * @return Json
	 */
    function comment_like(Request $request)
    {
        $id = $request->param('id');
        $res = UsersService::like($id, $request->users_id, 'store_assess_comment');
        $res ? event('StoreAssessCommentIncLike', $id) : event('StoreAssessCommentDecLike', $id); //增加/减少  点赞数量
        if ($res) {
            $pro = StoreAssessComment::find($id);
            UsersRelated::create(['users_id' => $pro->users_id, 'type' => 4, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $id]);
        }
        writeJson($res);
    }

    /**
     * 删除
     * @param Request $request
     * @return Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    function delete(Request $request)
    {
        $ids = $request->post('ids');
        StoreAssess::where(['users_id'=>$request->users_id])->whereIn('id',$ids)->select()->delete();
        writeJson();
    }
	
	
	/**
	 * 点赞
	 * @param Request $request
	 * @return Json
	 */
    function like(Request $request)
    {
        $id = $request->post('id');
        $res = UsersService::like($id, $request->users_id, 'store_assess');
        $res ? event('StoreAssessIncLike', $id) : event('StoreAssessDecLike', $id); //增加/减少  点赞数量
        if ($res) {
            $pro = StoreAssess::find($id);
            UsersRelated::create(['users_id' => $pro->users_id, 'type' => 3, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $id]);
        }
        writeJson($res);
    }
	
	/**
	 * 收藏
	 * @param Request $request
	 * @return Json
	 */
    function collect(Request $request)
    {
        $id = $request->post('id');
        $res = UsersService::collect($id, $request->users_id, 'store_assess');
        $res ? event('StoreAssessIncCollect', $id) : event('StoreAssessDecCollect', $id); //增加/减少  收藏数量
        if ($res) {
            $pro = StoreAssess::find($id);
            UsersRelated::create(['users_id' => $pro->users_id, 'type' => 7, 'from_users_id' => $request->users_id, 'scene' => 'Store', 'pro_id' => $id]);
        }
        writeJson($res);
    }
	
	
    /**
     * 采集
     */
    function get_data()
    {
//        $rows = Http::get('https://restapi.amap.com/v5/place/text', [
//            'key' => 'ad941626aed3c16b84c28562865314a3',
//            'keywords' => '中餐厅',
//            'region' => '1852',
//            'city_limit' => true,
//            'page_size' => 25,
//            'page_num' => 1,
//            'show_fields' => 'children,business,photos',
//        ]);
//        $rows = json_decode($rows);
//        writeJson($rows->pois);
	    
	    ignore_user_abort(true); //连接断开 继续执行.
	    
	    set_time_limit(0); // 执行时间无限制
	    ini_set("memory_limit","-1");
	    
        $class = StoreClass::where(['pid' => 0])->column('id'); //一级分类ids
        $sec_class = StoreClass::whereIn('pid', $class)->column('id'); //二级分类ids
        $store_class = Store::group('class_id')->column('class_id'); //找出所有店铺分类
        $rows = StoreClass::whereIn('pid', $sec_class)
	        ->whereNotIn('id',$store_class)
	        ->select(); //找出三级分类并且没有店铺的id

        foreach ($rows as $row) {
            for ($i = 1; $i <= 99999; $i++) {
                $res = Http::get('https://restapi.amap.com/v5/place/text', [
                    'key' => 'ad941626aed3c16b84c28562865314a3',
                    'keywords' => $row->name,
                    'region' => '香港特别行政区',
                    'city_limit' => true,
                    'page_size' => 25,
                    'page_num' => $i,
                    'show_fields' => 'children,business,photos',
                ]);

                $res = json_decode($res);
                if ($res->status != '1') {
                    writeJson(0,$res->info);
                }
                foreach ($res->pois as $v) {
					if (!isset($v->id)){
						continue;
					}
					$store = Store::where(['unique' => $v->id])->find();
					if (!$store){
						$arr = [
							'class_id' => $row->id,
							'title' => $v->name ?? '',
							'open_times' => $v->business->opentime_week ?? '',
							'mobile' => $v->business->tel ?? '',
							'type' => $v->type ?? '',
							'address' => $v->address ?? '',
							'unique' => $v->id ?? '',
						];
						if (isset($v->location)) {
							list($lng, $lat) = explode(',', $v->location);
							list($lngitude,$latitude) = GpsUtils::gcj02ToWgs84((float)$lng,(float)$lat);
							$arr['longitude'] = $lngitude;
							$arr['latitude'] = $latitude;
							$ids = HkArea::where([['top', '>=', $latitude], ['bottom', '<=', $latitude], ['left', '<=', $lngitude], ['right', '>=', $lngitude]])->column('id');
							$ids = implode(',', $ids);
							$arr['hk_area_ids'] = $ids;
						}
						if (isset($v->photos)) {
							$arr['images'] = implode(',', array_column($v->photos, 'url'));
							$arr['logo_image'] = array_column($v->photos, 'url')[0];
						}
						Store::create($arr);
					}
                
	           
                }
                if ($res->count < 25) {
                    break;
                }

            }
        }
        writeJson();
    }


}
